package pri.damai.xiaowu.auth.security.config;

import com.google.common.collect.Sets;
import com.fasterxml.classmate.TypeResolver;
import pri.damai.xiaowu.auth.security.model.LoginData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import pri.damai.xiaowu.common.security.config.XiaoWuSecurityProperties;
import springfox.documentation.builders.*;
import springfox.documentation.schema.*;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ApiListingScannerPlugin;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static java.util.Collections.singletonList;

/**
 * 自定义接口信息
 * @Desc
 * @Author DaMai
 * @Date 2021/5/12 17:07
 * 但行好事，莫问前程。
 */
@Component
public class SwaggerMyApiPlugin implements ApiListingScannerPlugin {

    @Resource
    XiaoWuSecurityProperties securityProperties;
    @Value("${spring.application.name}")
    String applicationName;

    private final CachingOperationNameGenerator operationNames;

    public SwaggerMyApiPlugin(CachingOperationNameGenerator operationNames) {
        this.operationNames = operationNames;
    }

    @Override
    public List<ApiDescription> apply(DocumentationContext context) {

        Operation operation = getTokenApi();
        ApiDescription loginDescription = new ApiDescription(applicationName, securityProperties.getLoginUrl(),
                "登录", "", singletonList(operation), false);

        ApiDescription logoutDescription = new ApiDescription(applicationName, "/logout",
                "登出", "", singletonList(getLogoutApi()), false);

        return Arrays.asList(loginDescription, logoutDescription);
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return documentationType.equals(DocumentationType.OAS_30);
    }

    public Operation getLogoutApi() {
        OperationBuilder builder = new OperationBuilder(operationNames);
        Operation operation = builder.method(HttpMethod.POST)
                .summary("登出")
                .notes("删除 Token")
                .consumes(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
                .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
                .tags(Sets.newHashSet("Token 操作"))
                .requestParameters(Collections.singletonList(
                        new RequestParameterBuilder()
                                .name(HttpHeaders.AUTHORIZATION)
                                .in(ParameterType.HEADER)
                                .query(s -> s.model(m -> m.scalarModel(ScalarType.STRING)))
                                .description("Token")
                                .examples(singletonList(new Example("2", " ", " ", "", " ", "string")))
                                .required(false)
                                .build()
                ))
                .responses(responses())
                .build();
        return operation;
    }

    public Operation getTokenApi() {

        OperationBuilder builder = new OperationBuilder(operationNames);
        Operation operation = builder.method(HttpMethod.POST)
                .summary("获取Token")
                .notes("用于获取Token")
                .consumes(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
                .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
                .tags(Sets.newHashSet("Token 操作"))
                //.requestBody(getRequestBody())
                //.requestParameters(getTokenApiParameter())
                .parameters(Arrays.asList(
                        new ParameterBuilder()
                                .type(new TypeResolver().resolve(LoginData.class))
                                .name("登录参数")
                                .description("登录参数")
                                .required(true)
                                .parameterType("body")
                                .modelRef(new ModelRef("LoginData"))
                                .build())
                )
                .responses(responses())
                .build();
        return operation;
    }

    public RequestBody getRequestBody() {
        return new RequestBody("", Sets.newHashSet(), true, null);
    }

    public Collection<RequestParameter> getTokenApiParameter() {
        return Arrays.asList(
                new RequestParameterBuilder()
                        .name("username")
                        .in(ParameterType.BODY)
                        .query(s -> s.model(m -> m.scalarModel(ScalarType.STRING)))
                        .description("用户名")
                        .examples(singletonList(new Example("2", " ", " ", "张三", " ", "string")))
                        .required(false)
                        .build()
                ,
                new RequestParameterBuilder()
                        .name("password")
                        .in(ParameterType.BODY)
                        .query(s -> s.model(m -> m.scalarModel(ScalarType.STRING)))
                        .description("密码")
                        .examples(singletonList(new Example("3", " ", " ", "zhangsan", " ", "string")))
                        .required(false)
                        .build()
                ,
                new RequestParameterBuilder()
                        .name("commonLoginVerifyCode")
                        .in(ParameterType.BODY)
                        .query(s -> s.model(m -> m.scalarModel(ScalarType.STRING)))
                        .description("登录验证码")
                        .examples(singletonList(new Example("4", " ", " ", "222222", " ", "string")))
                        .required(false)
                        .build()
                ,
                new RequestParameterBuilder()
                        .name("loginType")
                        .in(ParameterType.BODY)
                        .query(s -> s.model(m -> m.scalarModel(ScalarType.STRING)))
                        .description("登录类型")
                        .examples(singletonList(new Example("5", " ", " ", "usernameCode", " ", "string")))
                        .required(false)
                        .build()
        );
    }

    private Collection<Response> responses() {
        return singletonList(new ResponseBuilder()
                .code("200")
                .description("success")
                .representation(MediaType.APPLICATION_JSON)
                .apply(r -> r.model(m -> m.scalarModel(ScalarType.STRING))
                        .build())
                .build());
    }
}
